#pragma once
#include "InetAddr.hpp"
#include "Listener.hpp"
#include <unordered_map>
#include "Common.hpp"
#include <sys/epoll.h>
#include"Epoller.hpp"
#include"Connection.hpp"

using namespace hcc;

const static int gnum = 128;

class Reactor
{
public:
    Reactor() : _isrunning(false), _epoller(std::make_unique<Epoller>())
    {
    }
    void AddConnection(int fd,uint32_t events,InetAddr addr,int type)
    {
        //构建一个 epoll
        Connection* con=new Connection(fd);
        con->SetEvent(events);
        con->SetType(type);
        con->SetReactor(this);//将当前对象设置进入所有conn对象中
        con->SetAddr(addr);

        //设置对象的上层处理，就是不同的fd，我们应该进行不同的处理
        if(con->GetType() == ListenConnection)
        {
            con->RegisterHandler(_OnConnect,nullptr,nullptr);
        }
        else 
        {
            con->RegisterHandler(_OnRecver,_OnSender,_OnExcepter);
        }

        //将fd和events写进内核，托管给epoll
        if(!_epoller->AddEvent(fd,events))
        return ;
        
        //存进reactor（反应堆）
        _conn.insert(std::make_pair(fd,con));
    }
    void EnableConnectionReadWrite(int fd,bool readable,bool writeable)
    {
        if(!IsConnectionExists(fd))
        return ;
        uint32_t events=((readable?EPOLLIN:0)|(writeable?EPOLLOUT:0)|EPOLLET);
        _conn[fd]->SetEvent(events);
        
        //修改epoll
        _epoller->ModEvent(_conn[fd]->Sockfd(),_conn[fd]->GetEvents());
    }
    void DelConnection(int sockfd)
    {
        if(!IsConnectionExists(sockfd))
        {
            return;
        }
        //从内核中移除
        _epoller->DelEvent(sockfd);
        //关闭sockfd
        _conn[sockfd]->Close();
        //从当前管理中移除
        delete _conn[sockfd];
        _conn.erase(sockfd);
    }
    void SetOnNormalHandler(Handler_t onrecver,Handler_t onsender,Handler_t onexcepter)
    {
        _OnRecver=onrecver;
        _OnSender=onsender;
        _OnExcepter=onexcepter;
    }
    void SetOnConnect(Handler_t onconnect)
    {
        _OnConnect=onconnect;
    }
    void LoopOnce(int timeout)
    {
        int n = _epoller->Wait(revs, gnum, timeout);
        for (int i = 0; i < n; i++)
        {
            int sockfd = revs[i].data.fd;
            uint32_t revents = revs[i].events;
            if (revents & EPOLLIN)
            {
                if (IsConnectionExists(sockfd) && _conn[sockfd]->_handler_recver)
                    _conn[sockfd]->_handler_recver(_conn[sockfd]); // 读事件就绪，派发给对应的连接
            }
            if (revents & EPOLLOUT)
            {
                
                if (IsConnectionExists(sockfd) && _conn[sockfd]->_handler_sender)
                    _conn[sockfd]->_handler_sender(_conn[sockfd]) ; // 写事件就绪，派发给对应的连接
            }
        }
    }
    bool IsConnectionExists(int sockfd)
    {
        return _conn.count(sockfd);
    }
    void Dispatchar()
    {
        int timeout = -1;
        _isrunning = true;
        while (true)
        {
            LoopOnce(timeout); // 默认是阻塞的
            // 这里可以做其他事情
            PrintDebug();
        }
        _isrunning = false;
    }
    void PrintDebug()
    {
        std::string fdlist;
        for (auto &conn : _conn)
        {
            fdlist += std::to_string(conn.second->Sockfd()) + " ";
        }
        LOG(DEBUG, "epoll管理的fd列表: %s\n", fdlist.c_str());
    }

private:
    std::unordered_map<int, Connection *> _conn;
    std::unique_ptr<Multiplex> _epoller;
    bool _isrunning;
    struct epoll_event revs[gnum];

    // 定义处理函数

    // 1.处理新连接
    Handler_t _OnConnect;
    // 2.处理普通的sockfd  主要是IO处理
    Handler_t _OnRecver;
    Handler_t _OnSender;
    Handler_t _OnExcepter;
};